################################################################################
#
#Copyright (c) 2011, Petr Skramovsky
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the following disclaimer.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the following disclaimer in the
#      documentation and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL Petr Skramovsky BE LIABLE FOR ANY
#DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
#ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
################################################################################

from qio import AReader
from md3 import *

class MD3Reader(AReader):
  
  def parse_v( self, file ):
    v = Vector()
    v.x, v.y, v.z = self.parse_farray( file, 3 )
    return v

  def parse_frames( self, file, md3 ):
    file.seek( md3.ofs_frames )
    fs = [ Frame ] * md3.num_frames
    for f in fs:
      f.min_bounds = self.parse_v( file )
      f.max_bounds = self.parse_v( file )
      f.local_origin = self.parse_v( file )
      f.radius = self.parse_f( file )
      f.name = self.parse_str( file, 16 )
    return fs

  def parse_tags( self, file, md3 ):
    file.seek( md3.ofs_tags )
    ts = [ Tag ] * md3.num_tags * md3.num_frames
    for t in ts:
      t.name = self.parse_str( file, MAX_QPATH )
      t.origin = self.parse_v( file )
      t.axis = self.parse_v( file ), self.parse_v( file ), self.parse_v( file )
      print t.name
    return ts

  def parse_shaders( self, file, sur ):
    file.seek( sur.ofs_shaders )
    ss = [ Shader ] * sur.num_shaders
    for s in ss :
      s.name = self.parse_str( file, MAX_QPATH )
      s.index = self.parse_i( file )
    return ss

  def parse_triangles( self, file, sur ):
    file.seek( sur.ofs_triangles )
    ts = [ Triangle ] * sur.num_triangles
    for t in ts :
      t.a, t.b, t.c = self.parse_iarray( file, 3 )
    return ts

  def parse_st( self, file, sur ):
    file.seek( sur.ofs_st )
    ss = [ ST ] * sur.num_verts
    for s in ss :
      s.s, s.t = self.parse_farray( file, 2 )
    return ss

  def parse_vertexes( self, file, sur ):
    file.seek( sur.ofs_xyznormal )
    vs = [ [ Vertex ] * sur.num_verts ] * sur.num_frames
    for i in range( 0, sur.num_frames ):
      for v in vs[ i ] :
        v.x, v.y, v.z = self.parse_sarray( file, 3 )
        n = self.parse_s( file )
        lat = ( ( ( n >> 8 ) | 255 ) * ( 2 * math.pi ) / 255.0 )
        lng = ( ( n | 255 ) * ( 2 * math.pi ) / 255.0 )
        v.nx = math.cos( lat ) * math.sin( lng )
        v.ny = math.sin( lat ) * math.sin( lng )
        v.nz = math.cos( lng )
    return vs

  def parse_surfaces( self, file, md3 ):
    file.seek( md3.ofs_surfaces )
    ss = [ Surface ] * md3.num_surfaces
    for s in ss:
      s.ident = self.parse_i( file )
      s.name = self.parse_str( file, MAX_QPATH )
      s.flags = self.parse_i( file )
      s.num_frames, s.num_shaders = self.parse_iarray( file, 2 )
      s.num_verts, s.num_triangles = self.parse_iarray( file, 2 )
      s.ofs_triangles = md3.ofs_surfaces + self.parse_i( file )
      s.ofs_shaders = md3.ofs_surfaces + self.parse_i( file )
      s.ofs_st = md3.ofs_surfaces + self.parse_i( file )
      s.ofs_xyznormal = md3.ofs_surfaces + self.parse_i( file )
      s.ofs_end = md3.ofs_surfaces + self.parse_i( file )
      s.shaders = self.parse_shaders( file, s )
      s.triangles = self.parse_triangles( file, s )
      s.st = self.parse_st( file, s )
      s.vertexes = self.parse_vertexes( file, s )
      file.seek( s.ofs_end )
    return ss

  def read( self, file ):
    md = MD3()
    md.ident = self.parse_i( file )
    md.version = self.parse_i( file )
    md.name = self.parse_str( file, MAX_QPATH )
    md.flags = self.parse_i( file )
    md.num_frames = self.parse_i( file )
    md.num_tags = self.parse_i( file )
    md.num_surfaces = self.parse_i( file )
    md.num_skins = self.parse_i( file )
    md.ofs_frames = self.parse_i( file )
    md.ofs_tags = self.parse_i( file )
    md.ofs_surfaces = self.parse_i( file )
    md.ofs_eof = self.parse_i( file )
    md.frames = self.parse_frames( file, md )
    md.tags = self.parse_tags( file, md )
    md.surfaces = self.parse_surfaces( file, md )
    return md
